unit gamedataformunit;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, Buttons,
  StdCtrls, database, fpjson;

type

  { TGameDataForm }

  TGameDataForm = class(TForm)
    ActorIdComboBox: TComboBox;
    EnemyIdComboBox: TComboBox;
    ActorParamComboBox: TComboBox;
    CharIdComboBox: TComboBox;
    EnemyParamComboBox: TComboBox;
    CharParamParamComboBox: TComboBox;
    EnemyRadioButton: TRadioButton;
    CharRadioButton: TRadioButton;
    GameComboBox: TComboBox;
    PartyRadioButton: TRadioButton;
    ItemComboBox: TComboBox;
    EcCancelBitBtn: TBitBtn;
    EcOkBitBtn: TBitBtn;
    EcResultLineBevel: TBevel;
    EcResultPanel: TPanel;
    GameDataGroupBox: TGroupBox;
    ActorRadioButton: TRadioButton;
    GameRadioButton: TRadioButton;
    WeaponComboBox: TComboBox;
    ItemRadioButton: TRadioButton;
    ArmourComboBox: TComboBox;
    PartyComboBox: TComboBox;
    WeaponRadioButton: TRadioButton;
    ArmourRadioButton: TRadioButton;
    procedure RadioButtonChange(Sender: TObject);
  private
    Db: TDatabase;
    Troop: TJSONObject;

    procedure InitComboBoxes;
    procedure UpdateEnabledState;
    procedure PresetOldData(OldData: TJSONArray);
  public
    function SelectGameData(ADb: TDatabase; ATroop: TJSONObject;
                                            OldData: TJSONArray): Boolean;
    function GetArgs: TJSONArray;

  end;

  TGameDataType = (gdtItem = 0, gdtWeapon = 1, gdtArmour = 2, gdtActorData = 3,
                gdtEnemyData = 4, gdtCharData = 5, gdtPartyMemberId = 6,
                gdtGameParam = 7);

var
  GameDataForm: TGameDataForm;

implementation

{$R *.lfm}

uses
  comboboxhelper, globals, namehelper, constants;

resourcestring
  rsPartyLeader = 'Leader';
  rsPartyMember = 'Member #%d';
  rsUnnamedEvent = 'Event #%d';
  rsUnnamedEnemyId = '#%d';
  rsNamedEnemyId = '#%d %s';


{ TGameDataForm }

procedure TGameDataForm.RadioButtonChange(Sender: TObject);
begin
  UpdateEnabledState;
end;

procedure TGameDataForm.InitComboBoxes;
  procedure FillCharacters;
  var
    Events: TJSONArray;
    I: Integer;
  begin
    with CharIdComboBox.Items do begin
      BeginUpdate;
      Clear;

      Add(PreprocessComboboxValue(rsPlayerChar));
      Add(PreprocessComboboxValue(rsThisEvent));
      if (Game.Map <> nil) and Game.Map.Find('events', Events) then
         for I := 1 to Events.Count - 1 do begin
           if Events[I].JSONType = jtObject then
              Add(Events.Objects[I].Strings['name'])
           else
             Add(rsUnnamedEvent.Format([I])); {TODO: don't show unnamed events}
         end;

      EndUpdate;
    end;
    CharIdComboBox.ItemIndex := 0;
  end;

  procedure FillEnemyIds;
  var
    I: Integer;
    Members: TJSONArray;
    EnemyDbId: Integer;
  begin
    with EnemyIdComboBox.Items do begin
      BeginUpdate;
      Clear;
      for I := 1 to 8 do begin
        if (Troop <> nil) and (Troop.Find('members', Members))
                              and (Members.Count >= I) then begin
          EnemyDbId := Members.Objects[I-1].Integers['enemyId'];
          Add(rsNamedEnemyId.Format([I, Db.GetEnemyName(EnemyDbId, False)]));
        end else
          Add(rsUnnamedEnemyId.Format([I]));
      end;
      EndUpdate;
    end;
    EnemyIdComboBox.ItemIndex := 0;
  end;

  procedure FillPartyMemberIds;
  var
    I: Integer;
  begin
    with PartyComboBox.Items do begin
      BeginUpdate;
      Clear;

      Add(rsPartyLeader);
      for I := 2 to 8 do begin
        Add(rsPartyMember.Format([I]));
      end;
      EndUpdate;
    end;
    PartyComboBox.ItemIndex := 0;
  end;
begin
  FillDbArrayComboBox(ItemComboBox, Db.Items);
  FillDbArrayComboBox(WeaponComboBox, Db.Weapons);
  FillDbArrayComboBox(ArmourComboBox, Db.Armours);
  FillDbArrayComboBox(ActorIdComboBox, Db.Actors);
  FillNamesComboBox(ActorParamComboBox, Db, @SetVar_GetGameData_ActorData, 0, 11);
  ActorParamComboBox.ItemIndex := 0;
  FillEnemyIds;
  FillNamesComboBox(EnemyParamComboBox, Db, @SetVar_GetGameData_EnemyData, 0, 9);
  EnemyParamComboBox.ItemIndex := 0;
  FillCharacters;
  FillNamesComboBox(CharParamParamComboBox, @SetVar_GetGameData_CharDataDesc,
                                            0, 4);
  CharParamParamComboBox.ItemIndex := 0;

  FillPartyMemberIds;
  FillNamesComboBox(GameComboBox, @SetVar_GetGameData_Other, 0, 9);
  GameComboBox.ItemIndex := 0;
end;

procedure TGameDataForm.UpdateEnabledState;
begin
  ItemComboBox.Enabled := ItemRadioButton.Checked;
  WeaponComboBox.Enabled := WeaponRadioButton.Checked;
  ArmourComboBox.Enabled := ArmourRadioButton.Checked;
  ActorIdComboBox.Enabled := ActorRadioButton.Checked;
  ActorParamComboBox.Enabled := ActorRadioButton.Checked;
  EnemyIdComboBox.Enabled := EnemyRadioButton.Checked;
  EnemyParamComboBox.Enabled := EnemyRadioButton.Checked;
  CharIdComboBox.Enabled := CharRadioButton.Checked;
  CharParamParamComboBox.Enabled := CharRadioButton.Checked;
  PartyComboBox.Enabled := PartyRadioButton.Checked;
  GameComboBox.Enabled := GameRadioButton.Checked;
end;

procedure TGameDataForm.PresetOldData(OldData: TJSONArray);
  procedure PresetSingleId(RadioButton: TRadioButton; ComboBox: TComboBox);
  begin
    RadioButton.Checked := True;
    ComboBox.ItemIndex := OldData.Integers[1] - 1;
  end;

  procedure PresetActorData;
  begin
    ActorRadioButton.Checked := True;
    ActorIdComboBox.ItemIndex := OldData.Integers[1] - 1;
    if (OldData[2].JSONType = jtNumber) then
      ActorParamComboBox.ItemIndex := OldData.Integers[2];
  end;

  procedure PresetEnemyData;
  begin
    EnemyRadioButton.Checked := True;
    EnemyIdComboBox.ItemIndex := OldData.Integers[1];
    if (OldData[2].JSONType = jtNumber) then
      EnemyParamComboBox.ItemIndex := OldData.Integers[2];
  end;

  procedure PresetCharData;
  begin
    CharRadioButton.Checked := True;
    CharIdComboBox.ItemIndex := OldData.Integers[1] + 1;
    if (OldData[2].JSONType = jtNumber) then
      CharParamParamComboBox.ItemIndex := OldData.Integers[2];
  end;

  procedure PresetPartyMemberData;
  begin
    PartyRadioButton.Checked := True;
    PartyComboBox.ItemIndex := OldData.Integers[1];
  end;

  procedure PresetGameParamData;
  begin
    GameRadioButton.Checked := True;
    GameComboBox.ItemIndex := OldData.Integers[1];
  end;

var
  DataType: TGameDataType;
begin
  if (OldData = nil) or (OldData.Count < 2) or (OldData[0].JSONType <> jtNumber)
              or (OldData.Integers[0] < Ord(Low(TGameDataType)))
              or (OldData.Integers[0] > Ord(High(TGameDataType)))
              or (OldData[1].JSONType <> jtNumber) then
     Exit;

  DataType := TGameDataType(OldData.Integers[0]);

  case DataType of
    gdtItem: PresetSingleId(ItemRadioButton, ItemComboBox);
    gdtWeapon: PresetSingleId(WeaponRadioButton, WeaponComboBox);
    gdtArmour: PresetSingleId(ArmourRadioButton, ArmourComboBox);
    gdtActorData: PresetActorData;
    gdtEnemyData: PresetEnemyData;
    gdtCharData: PresetCharData;
    gdtPartyMemberId: PresetPartyMemberData;
    gdtGameParam: PresetGameParamData;
  end;
end;

function TGameDataForm.SelectGameData(ADb: TDatabase; ATroop: TJSONObject;
                                           OldData: TJSONArray): Boolean;
begin
  Db := ADb;
  Troop := ATroop;
  InitComboBoxes;
  UpdateEnabledState;

  PresetOldData(OldData);
  ShowModal;

  Result := ModalResult = mrOK;
end;

function TGameDataForm.GetArgs: TJSONArray;
var
  Args: TJSONArray;
begin
  Args := TJSONArray.Create;

  if ItemRadioButton.Checked then begin
    Args.Add(Ord(gdtItem));
    Args.Add(ItemComboBox.ItemIndex + 1);
  end else if WeaponRadioButton.Checked then begin
    Args.Add(Ord(gdtWeapon));
    Args.Add(WeaponComboBox.ItemIndex + 1);
  end else if ArmourRadioButton.Checked then begin
    Args.Add(Ord(gdtArmour));
    Args.Add(ArmourComboBox.ItemIndex + 1);
  end else if ActorRadioButton.Checked then begin
    Args.Add(Ord(gdtActorData));
    Args.Add(ActorIdComboBox.ItemIndex + 1);
    Args.Add(ActorParamComboBox.ItemIndex);
  end else if EnemyRadioButton.Checked then begin
    Args.Add(Ord(gdtEnemyData));
    Args.Add(EnemyIdComboBox.ItemIndex);
    Args.Add(EnemyParamComboBox.ItemIndex);
  end else if CharRadioButton.Checked then begin
    Args.Add(Ord(gdtCharData));
    Args.Add(CharIdComboBox.ItemIndex - 1);
    Args.Add(CharParamParamComboBox.ItemIndex);
  end else if PartyRadioButton.Checked then begin
    Args.Add(Ord(gdtPartyMemberId));
    Args.Add(PartyComboBox.ItemIndex);
  end else if GameRadioButton.Checked then begin
    Args.Add(Ord(gdtGameParam));
    Args.Add(GameComboBox.ItemIndex);
  end;

  GetArgs := Args;
end;

end.

